package com.sas.service.impl;

import com.sas.entity.Employee;
import com.sas.entity.Room;
import com.sas.entity.Schedule;
// 移除不存在的枚举导入，统一使用整数类型
import com.sas.repository.EmployeeRepository;
import com.sas.repository.RoomRepository;
import com.sas.repository.ScheduleRepository;
import com.sas.service.ScheduleService;
import com.sas.service.SchedulingAlgorithmService;
import org.springframework.beans.factory.annotation.Autowired;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 排班服务实现类
 */
@Service
@Transactional
public class ScheduleServiceImpl implements ScheduleService {

    private static final Logger log = LoggerFactory.getLogger(ScheduleServiceImpl.class);
    @Autowired
    private ScheduleRepository scheduleRepository;
    @Autowired
    private EmployeeRepository employeeRepository;
    @Autowired
    private RoomRepository roomRepository;
    @Autowired
    private SchedulingAlgorithmService schedulingAlgorithmService;

    @Override
    public Schedule save(Schedule schedule) {
        schedule.setCreateTime(LocalDateTime.now());
        schedule.setUpdateTime(LocalDateTime.now());
        return scheduleRepository.save(schedule);
    }

    @Override
    public Optional<Schedule> findById(Long id) {
        return scheduleRepository.findById(id);
    }

    @Override
    public List<Schedule> findAll() {
        return scheduleRepository.findAll();
    }

    @Override
    public List<Schedule> findByEmployeeId(Long employeeId) {
        return scheduleRepository.findByEmployeeId(employeeId);
    }

    @Override
    public List<Schedule> findByRoomId(Long roomId) {
        return scheduleRepository.findByRoomId(roomId);
    }

    @Override
    public List<Schedule> findByScheduleDate(LocalDate scheduleDate) {
        return scheduleRepository.findByScheduleDate(scheduleDate);
    }

    @Override
    public List<Schedule> findByEmployeeIdAndDateRange(Long employeeId, LocalDate startDate, LocalDate endDate) {
        return scheduleRepository.findByEmployeeIdAndDateRange(employeeId, startDate, endDate);
    }

    @Override
    public List<Schedule> findByRoomIdAndDateRange(Long roomId, LocalDate startDate, LocalDate endDate) {
        return scheduleRepository.findByRoomIdAndDateRange(roomId, startDate, endDate);
    }

    @Override
    public Schedule update(Schedule schedule) {
        schedule.setUpdateTime(LocalDateTime.now());
        return scheduleRepository.save(schedule);
    }

    @Override
    public void deleteById(Long id) {
        scheduleRepository.deleteById(id);
    }

    @Override
    public Map<String, Object> autoSchedule(LocalDate startDate, LocalDate endDate) {
        log.info("开始自动排班，时间段: {} - {}", startDate, endDate);
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 使用排班算法服务进行自动排班
            List<Integer> employeeTypes = Arrays.asList(1, 2, 3);
            
            // 设置工作时间（早班：8:00-16:00，晚班：16:00-24:00）
            LocalTime morningStart = LocalTime.of(8, 0);
            LocalTime morningEnd = LocalTime.of(16, 0);
            LocalTime eveningStart = LocalTime.of(16, 0);
            LocalTime eveningEnd = LocalTime.of(24, 0);
            
            List<Schedule> generatedSchedules = new ArrayList<>();
            
            // 生成早班排班
            List<Schedule> morningSchedules = schedulingAlgorithmService.autoSchedule(
                startDate, endDate, employeeTypes, morningStart, morningEnd
            );
            generatedSchedules.addAll(morningSchedules);
            
            // 生成晚班排班
            List<Schedule> eveningSchedules = schedulingAlgorithmService.autoSchedule(
                startDate, endDate, employeeTypes, eveningStart, eveningEnd
            );
            generatedSchedules.addAll(eveningSchedules);
            
            // 优化排班负载均衡
            schedulingAlgorithmService.optimizeScheduleBalance(startDate, endDate);
            
            // 获取统计信息
            Map<String, Object> statistics = schedulingAlgorithmService.getSchedulingStatistics(startDate, endDate);
            
            result.put("success", true);
            result.put("message", "自动排班完成");
            result.put("generatedCount", generatedSchedules.size());
            result.put("statistics", statistics);
            result.put("schedules", generatedSchedules);
            
            log.info("自动排班完成，生成排班数量: {}", generatedSchedules.size());
            
        } catch (Exception e) {
            log.error("自动排班失败", e);
            result.put("success", false);
            result.put("message", "自动排班失败: " + e.getMessage());
            result.put("generatedCount", 0);
        }
        
        return result;
    }

    @Override
    public boolean hasScheduleConflict(Schedule schedule) {
        // 检查员工时间冲突
        List<Schedule> employeeSchedules = scheduleRepository.findByEmployeeIdAndScheduleDate(
            schedule.getEmployeeId(), schedule.getScheduleDate()
        );
        
        for (Schedule existing : employeeSchedules) {
            if (existing.getId() != null && existing.getId().equals(schedule.getId())) {
                continue; // 跳过自己
            }
            
            // 检查时间重叠
            if (isTimeOverlap(schedule.getStartTime(), schedule.getEndTime(),
                            existing.getStartTime(), existing.getEndTime())) {
                return true;
            }
        }
        
        // 检查房间时间冲突
        List<Schedule> roomSchedules = scheduleRepository.findByRoomIdAndScheduleDate(
            schedule.getRoomId(), schedule.getScheduleDate()
        );
        
        for (Schedule existing : roomSchedules) {
            if (existing.getId() != null && existing.getId().equals(schedule.getId())) {
                continue; // 跳过自己
            }
            
            // 检查时间重叠
            if (isTimeOverlap(schedule.getStartTime(), schedule.getEndTime(),
                            existing.getStartTime(), existing.getEndTime())) {
                return true;
            }
        }
        
        return false;
    }

    /**
     * 检查时间是否重叠
     */
    private boolean isTimeOverlap(LocalTime start1, LocalTime end1, LocalTime start2, LocalTime end2) {
        return start1.isBefore(end2) && start2.isBefore(end1);
    }

    @Override
    public Map<String, Object> getEmployeeScheduleView(Long employeeId, LocalDate startDate, LocalDate endDate) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 获取员工信息
            Optional<Employee> employeeOpt = employeeRepository.findById(employeeId);
            if (!employeeOpt.isPresent()) {
                result.put("success", false);
                result.put("message", "员工不存在");
                return result;
            }
            
            Employee employee = employeeOpt.get();
            
            // 获取排班列表
            List<Schedule> schedules = findByEmployeeIdAndDateRange(employeeId, startDate, endDate);
            
            // 计算统计信息
            int totalWorkDays = (int) schedules.stream()
                .map(Schedule::getScheduleDate)
                .distinct()
                .count();
            
            int totalWorkHours = schedules.stream()
                .mapToInt(s -> (int) java.time.Duration.between(s.getStartTime(), s.getEndTime()).toHours())
                .sum();
            
            int overtimeHours = Math.max(0, totalWorkHours - (totalWorkDays * 8));
            
            // 估算工资（基于员工薪资等级）
            double estimatedSalary = calculateEstimatedSalary(employee, totalWorkHours, overtimeHours);
            
            result.put("success", true);
            result.put("employee", employee);
            result.put("schedules", schedules);
            result.put("statistics", Map.of(
                "totalWorkDays", totalWorkDays,
                "totalWorkHours", totalWorkHours,
                "overtimeHours", overtimeHours,
                "estimatedSalary", estimatedSalary
            ));
            
        } catch (Exception e) {
            log.error("获取员工排班视图失败", e);
            result.put("success", false);
            result.put("message", "获取员工排班视图失败: " + e.getMessage());
        }
        
        return result;
    }

    @Override
    public Map<String, Object> getAdminScheduleView(LocalDate startDate, LocalDate endDate) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 获取所有排班
            List<Schedule> allSchedules = scheduleRepository.findByDateRange(startDate, endDate);
            
            // 获取所有员工
            List<Employee> allEmployees = employeeRepository.findAll();
            
            // 按日期分组排班
            Map<LocalDate, List<Schedule>> schedulesByDate = allSchedules.stream()
                .collect(Collectors.groupingBy(Schedule::getScheduleDate));
            
            // 按员工分组排班
            Map<Long, List<Schedule>> schedulesByEmployee = allSchedules.stream()
                .collect(Collectors.groupingBy(Schedule::getEmployeeId));
            
            // 计算统计信息
            int totalEmployees = (int) allSchedules.stream()
                .map(Schedule::getEmployeeId)
                .distinct()
                .count();
            
            int totalSchedules = allSchedules.size();
            
            int totalHours = allSchedules.stream()
                .mapToInt(s -> (int) java.time.Duration.between(s.getStartTime(), s.getEndTime()).toHours())
                .sum();
            
            long pendingSchedules = allSchedules.stream()
                .filter(s -> s.getStatus() != null && s.getStatus() == 1)
                .count();
            
            result.put("success", true);
            result.put("schedules", allSchedules);
            result.put("employees", allEmployees);
            result.put("schedulesByDate", schedulesByDate);
            result.put("schedulesByEmployee", schedulesByEmployee);
            result.put("statistics", Map.of(
                "totalEmployees", totalEmployees,
                "totalSchedules", totalSchedules,
                "totalHours", totalHours,
                "pendingSchedules", pendingSchedules
            ));
            
        } catch (Exception e) {
            log.error("获取管理员排班视图失败", e);
            result.put("success", false);
            result.put("message", "获取管理员排班视图失败: " + e.getMessage());
        }
        
        return result;
    }

    @Override
    public Map<String, Object> getScheduleStatistics(LocalDate startDate, LocalDate endDate) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 使用排班算法服务获取统计信息
            Map<String, Object> statistics = schedulingAlgorithmService.getSchedulingStatistics(startDate, endDate);
            
            result.put("success", true);
            result.put("statistics", statistics);
            
        } catch (Exception e) {
            log.error("获取排班统计信息失败", e);
            result.put("success", false);
            result.put("message", "获取排班统计信息失败: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 计算估算工资
     */
    private double calculateEstimatedSalary(Employee employee, int totalWorkHours, int overtimeHours) {
        // 基础时薪（根据员工类型和薪资等级）
        double baseHourlyRate = getBaseHourlyRate(employee);
        
        // 正常工作时间工资
        double regularPay = (totalWorkHours - overtimeHours) * baseHourlyRate;
        
        // 加班工资（1.5倍）
        double overtimePay = overtimeHours * baseHourlyRate * 1.5;
        
        return regularPay + overtimePay;
    }

    /**
     * 获取基础时薪
     */
    private double getBaseHourlyRate(Employee employee) {
        // 根据员工类型和薪资等级计算基础时薪
        double baseRate = 20.0; // 基础时薪
        
        // 员工类型系数
        Integer type = employee.getEmployeeType();
        if (type != null) {
            switch (type) {
                case 1: // 全职
                    baseRate *= 1.5;
                    break;
                case 2: // 兼职
                    baseRate *= 1.2;
                    break;
                case 3: // 临时工
                    baseRate *= 1.0;
                    break;
                default:
                    break;
            }
        }
        
        // 薪资等级系数
        if (employee.getSalaryLevel() != null) {
            baseRate *= (1.0 + employee.getSalaryLevel() * 0.1);
        }
        
        return baseRate;
    }
}